//********************************************************************************************
//
// File : ip.h implement for Internet Protocol
//
//********************************************************************************************

#ifndef __IP_h__
#define __IP_h__

#include "BasicTypes.h"

class cIP
{
//*******************************************************************************
// constance
public:
    // General const for TCP/IP stack
    #define STR_DISCOVERY               ("ARP")
    #define STR_DISCOVERY_REPLY         ("I am:00,myIP,pt,Auto00")
    #define STR_DISCOVERY_ID_INDEX      (UDP_DATA_P + sizeof("I am:")-1)
    #define STR_DISCOVERY_IP_INDEX      (UDP_DATA_P + sizeof("I am:01,")-1)
    #define STR_DISCOVERY_PORT_INDEX    (UDP_DATA_P + sizeof("I am:01,myIP,")-1)
    #define STR_DISCOVERY_MAC_INDEX     (UDP_DATA_P + sizeof("I am:00,myIP,pt,")-1)

    #define SET_IP_ID_IDENTIFY_INDEX    (UDP_DATA_P + 1)
    #define SET_IP_IP_IDENTIFY_INDEX    (UDP_DATA_P + 1 + 2)
    #define SET_IP_PORT_IDENTIFY_INDEX  (UDP_DATA_P + 1 + 2 + 4)
    #define NEW_IP_PORT_INDEX           (UDP_DATA_P + 1 + 2 + 4 + 2)



    static const U8  MAC_ADDR_LEN       = 6;
    static const U8  IP_ADDR_LEN        = 4;

    static const U16 MAX_RXTX_BUFFER    = 600;

    // const use for MAC header
    static const U8  MAC_HEADER_LEN     = 14;

    static const U16 MAC_TYPE_ARP_VAL     = 0x0806;
    static const U8  MAC_TYPE_ARP_H_VAL   = 0x08;
    static const U8  MAC_TYPE_ARP_L_VAL   = 0x06;
    static const U16 MAC_TYPE_IP_VAL      = 0x0800;
    static const U8  MAC_TYPE_IP_H_VAL    = 0x08;
    static const U8  MAC_TYPE_IP_L_VAL    = 0x00;

    static const U8  MAC_DST_MAC_POS      = 0;
    static const U8  MAC_SRC_MAC_POS      = 6;
    static const U8  MAC_TYPE_H_POS       = 12;
    static const U8  MAC_TYPE_L_POS       = 13;

    // const use for IP header
    static const U8 IP_HEADER_LEN       = 20;

    static const U8 IP_PROTO_ICMP_V     = 0x01;
    static const U8 IP_PROTO_TCP_V      = 0x06;
    static const U8 IP_PROTO_UDP_V      = 0x11;
    static const U8 IP_V4_V             = 0x40;
    static const U8 IP_HEADER_LENGTH_V  = 0x05;

    static const U8 IP_P                = 0x0E;
    static const U8 IP_HEADER_VER_LEN_P = 0x0E;
    static const U8 IP_TOS_P            = 0x0F;
    static const U8 IP_TOTLEN_H_P       = 0x10;
    static const U8 IP_TOTLEN_L_P       = 0x11;
    static const U8 IP_ID_H_P           = 0x12;
    static const U8 IP_ID_L_P           = 0x13;
    static const U8 IP_FLAGS_H_P        = 0x14;
    static const U8 IP_FLAGS_L_P        = 0x15;
    static const U8 IP_TTL_P            = 0x16;
    static const U8 IP_PROTO_P          = 0x17;
    static const U8 IP_CHECKSUM_H_P     = 0x18;
    static const U8 IP_CHECKSUM_L_P     = 0x19;
    static const U8 IP_SRC_IP_P         = 0x1A;
    static const U8 IP_DST_IP_P         = 0x1E;


    // IP header structure
    typedef struct _IP_HEADER
    {
        U8          version_hlen;
        U8          type_of_service;
        U16         total_length;
        U16         indentificaton;
        U16         flagment;
        U8          time_to_live;
        U8          protocol;
        U16         checksum;
        U8          src_ip[IP_ADDR_LEN];
        U8          dest_ip[IP_ADDR_LEN];
    }IP_HEADER;

    // ARP packet structure
    typedef struct _ARP_PACKET
    {
        U16   hardware_type;
        U16   protocol_type;
        U8    hardware_length;
        U8    protocol_length;
        U16   opcode;
        U8    src_mac[MAC_ADDR_LEN];
        U8    src_ip[IP_ADDR_LEN];
        U8    dest_mac[MAC_ADDR_LEN];
        U8    dest_ip[IP_ADDR_LEN];
    } ARP_PACKET;

    // ICMP packet structure
    static const U8 ICMP_MAX_DATA = 32;
    typedef struct _ICMP_PACKET
    {
        U8  type;
        U8  code;
        U16 checksum;
        U16 identifier;
        U16 sequence_number;
        U8  data[ICMP_MAX_DATA];
    } ICMP_PACKET;

    typedef struct _UDP_HEADER
    {
        U16 src_port;
        U16 dst_port;
        U16 length;
        U16 checksum;
    } UDP_HEADER;

//*******************************************************************************
// variable
private:
    static U16 IdentifyCnt;
    static U8  s_pMacAddr[];
    static U8  s_pIPAddr[];
    static U16 s_UDPSrcPort;
    static U16 s_TCPSrcPort;

//*******************************************************************************
//function
public:
    static void InitReset();
    static void GenerateMacHeader ( U8 *pBuff, U16 iType, U8 *iDestMac );
    static void GenerateIpHeader ( U8 *pBuff, U16 iTotalLength, U8 iProtocol, U8 *iDestIP );
    static bool IsValidPacket ( U8 *rxtx_buffer );
    static U16  SoftwareChecksum(U8 *pBuff, U16 iLen, U32 iSum);
    static bool IPCmp(U8 *pIP);
    static bool MACCmp(U8 *pMAC);
    static bool UDPPortCmp(U8 *pPort);
    static bool TCPPortCmp(U8 *pPort);
    static inline U8* GetIPAddr()
    {
        return (s_pIPAddr);
    }
    static inline U8* GetMacAddr()
    {
        return (s_pMacAddr);
    }
    static inline U16 GetUDPPort()
    {
        return (s_UDPSrcPort);
    }
    static inline U16 GetTCPPort()
    {
        return (s_TCPSrcPort);
    }
    static void ChangeIPAndPort(U8* pBuff);
};

#endif

